/**
 * @file ListType.h
 * @author 严一涵 (yyhhenry@foxmail.com)
 * @brief 双向链表
 * @version 0.1
 * @date 2022-05-10
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#ifndef LIST_H_YYH
#define LIST_H_YYH
#include <stdlib.h>

/**
 * @brief 双向链表节点
 * @author 严一涵
 */
typedef struct ListNode
{
    void *ptr;
    struct ListNode *prev;
    struct ListNode *next;
} ListNode;

/**
 * @brief 链表节点释放
 * @author 严一涵
 * @param node 要释放的节点，释放后使用权销毁，禁止外部调用
 */
void ListNode_free(ListNode *node, void (*free_ptr)(void *));

/**
 * @brief 链表节点使用示例（用户应该自行定义对应的使用模型）
 * @author 严一涵
 * @return void* 所需的类型，例如int*
 */
void *void_ListNode(ListNode *node);

/**
 * @brief 双向链表
 * @author 严一涵
 */
typedef struct ListType
{
    ListNode *head;
    ListNode *tail;
    long long size;
    void (*free_ptr)(void *);
} ListType;

/**
 * @brief 双向链表构造函数
 * @author 严一涵
 * @return 链表指针
 * @param free_ptr 用于析构元素的函数，所有权应在其中销毁（即本身包含free）
 */
ListType *ListType_ListType(void (*free_ptr)(void *));

/**
 * @brief 双向链表插入函数
 * @author 严一涵
 * @param list 要操作的链表
 * @param node 在该节点前插入，如果插在末尾或插入到空链表则应该为NULL
 * @param ptr 要插入的节点的内容，调用该函数后使用权移交，禁止在外部删除
 * @return 新插入的节点
 */
ListNode *ListType_insert(ListType *list, ListNode *node, void *ptr);

/**
 * @brief 双向链表删除函数
 * @author 严一涵
 * @param list 要操作的链表
 * @param node 删除该节点，使用权销毁，请勿外部使用
 */
void ListType_remove(ListType *list, ListNode *node);

/**
 * @brief 删除双向链表
 * @author 严一涵
 * @param list 要删除的列表，所有权销毁，请勿外部使用
 */
void ListType_free(ListType *list);

/**
 * @brief 引用型指针的销毁过程，不作任何处理
 */
void Ref_free(void *p);
#endif // LIST_H_YYH
